package edu.hawaii.halealohacli.command;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import org.junit.Test;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.WattDepotClient;

/**
 * Test Class for the RankTowers class.
 * 
 * @author Sergey Negrashov
 * 
 */
public class TestRankTowers {

  /**
   * Url for the wattdepot server.
   */
  private String url = "http://server.wattdepot.org:8190/wattdepot/";

  /**
   * Argument array for the command.
   */
  private String args[] = { "2011-11-23", "2011-11-24" };

  /**
   * Checks that getTowerEnergyMapCount returns a right number of elements in the map.
   * 
   * @throws BadXmlException this exception will fail the test.
   * @throws MiscClientException this exception will fail the test.
   */
  @Test
  public void testGetTowerEnergyMapCount() throws BadXmlException, MiscClientException {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    command.initialize(args, client);
    command.execute();
    assertEquals("Test of TowerEnergyMap failed", 4, command.getTowerEnergyList().size());
  }

  /**
   * Checks that getTowerEnergyMapCount returns all of the towers in the map.
   * 
   * @throws BadXmlException this exception will fail the test.
   * @throws MiscClientException this exception will fail the test.
   */
  @Test
  public void testGetTowerEnergyMapValues() throws BadXmlException, MiscClientException {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    command.initialize(args, client);
    List<SortingObject<Double>> map = command.getTowerEnergyList();
    boolean mokihana = false;
    boolean ilima = false;
    boolean lehua = false;
    boolean lokelani = false;

    for (SortingObject<Double> tower : map) {
      if ("Mokihana".equals(tower.value)) {
        mokihana = true;
      }
      if ("Ilima".equals(tower.value)) {
        ilima = true;
      }
      if ("Lehua".equals(tower.value)) {
        lehua = true;
      }
      if ("Lokelani".equals(tower.value)) {
        lokelani = true;
      }
    }

    assertEquals("Test Mokihana failed", true, mokihana);
    assertEquals("Test Ilima failed", true, ilima);
    assertEquals("Test Lehua failed", true, lehua);
    assertEquals("Test Lokelani failed", true, lokelani);
  }

  /**
   * Check that printSorted returns text when the input parameters are valid.
   * 
   */
  @Test
  public void testPrintSortedGoodData() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    command.initialize(args, client);
    assertEquals("Test with good values failed", command.printSorted().isEmpty(), false);
  }

  /**
   * Checks that printSorted returns the correct error message when one of the arguments is not a
   * date.
   * 
   */
  @Test
  public void testPrintSortedBadData() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    args[1] = "Bad text";
    command.initialize(args, client);
    assertEquals("Test with bad values failed", command.printSorted(), "Argument \"" + args[1]
        + "\" is invalid.");
  }

  /**
   * Checks that printSorted returns the correct error message when one of the arguments is not a
   * valid date.
   * 
   */
  @Test
  public void testPrintSortedBadDates() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    args[0] = "2011-13-01";
    command.initialize(args, client);
    assertEquals("Test with bad dates failed", command.printSorted(), "Argument \"" + args[0]
        + "\" is invalid.");
  }

  /**
   * Checks that printSorted returns the correct error message when the start date is greater than
   * the end date.
   * 
   */
  @Test
  public void testPrintSortedBadRange() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    args[0] = "2011-12-31";
    command.initialize(args, client);
    assertEquals("Test with bad range failed", command.printSorted(),
        "End date must be greater than start date.");
  }

  /**
   * Checks that printSorted returns the correct error message when the end date is today.
   */
  @Test
  public void testPrintSortedSameDates() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    args[1] = args[0];
    command.initialize(args, client);
    assertEquals("Test with same dates failed", command.printSorted(),
        "End date must be greater than start date.");
  }

  /**
   * Checks that printSorted returns the correct error message when the end date is in the future.
   */
  @Test
  public void testPrintSortedBadEndDate() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
    Calendar cal = Calendar.getInstance();
    Date tomorrow = new Date(cal.getTimeInMillis() + (1000 * 60 * 60 * 24));
    args[1] = dateFormat.format(tomorrow);
    command.initialize(args, client);
    assertEquals("Test with bad end date failed", command.printSorted(),
        "The end date cannot be in the future.");
  }

  /**
   * Checks that printSorted returns data when the end date is today.
   */
  @Test
  public void testPrintSortedEndToday() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
    Calendar cal = Calendar.getInstance();
    args[1] = dateFormat.format(cal.getTime());
    command.initialize(args, client);
    assertTrue(
        "Test with end today failed",
        command.printSorted().startsWith(
            "For the interval " + args[0] + " to " + args[1]
                + ", energy consumption by tower was:"));
  }

  /**
   * Checks that printSorted returns the correct error message when an incorrect number of arguments
   * is given.
   */
  @Test
  public void testPrintSortedWrongNumberOfArguments() {
    WattDepotClient client = new WattDepotClient(url);
    RankTowers command = new RankTowers();
    String args[] = { "2011-11-01" };
    command.initialize(args, client);
    command.execute();
    assertEquals("Test with bad arguments failed", command.printSorted(), "Invalid arguments for "
        + command.getCommandName() + ".\n" + command.getCommandUsage());
  }

  /**
   * Checks that printSorted returns the correct error message when a null or invalid client is
   * given.
   */
  @Test
  public void testPrintSortedInvalidClient() {
    WattDepotClient client = new WattDepotClient(url + "error");
    RankTowers command = new RankTowers();
    command.initialize(args, null);
    assertEquals("Test with null client failed", command.printSorted(),
        "Could not connect to the server.");

    command.initialize(args, client);
    assertEquals("Test with invalid URL failed", command.printSorted(),
        "Could not connect to the server.");
  }

}
